﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using CsharpHttpHelper;
using CsharpHttpHelper.Enum;
using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.Zip;
using Newtonsoft.Json;
using 浏览器客户端.Helper;
using 浏览器客户端.Models;
using 浏览器客户端.Models.Model;
using Common = 浏览器客户端.Helper.Common;

namespace 浏览器客户端.Script
{
    public class CommonScript
    {
        private readonly LogScript _logger = new LogScript();

        /// <summary>
        /// 设定本地时间
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public Result<bool> SetLocalTime(DateTime time)
        {
            try
            {
                var isSuccess = SetTime.SetLocalTime(time);
                return new Result<bool>()
                {
                    Data = isSuccess
                };
            }
            catch (Exception e)
            {
                _logger.Error($"本地时间设定异常:{JsonConvert.SerializeObject(e)}", "同步时间");
                return new Result<bool>()
                {
                    Code = 1,
                    Message = "时间同步失败"
                };
            }
        }

        /// <summary>
        /// 获取本地配置文件
        /// </summary>
        /// <returns></returns>
        public LocalConfig GetLocalConfig()
        {
            return Config.Local;
        }
        
        /// <summary>
        /// 设定硬件配置信息
        /// </summary>
        /// <returns></returns>
        public Result<bool> SetDeviceConfig(string json)
        {
            if (Common.TryJsonParse(json, out SysClientVm data, out var error))
            {
                Config.Device = data;
                return new Result<bool>()
                {
                    Data = true
                };
            }
            return new Result<bool>
            {
                Code = 1,
                Message = $"解析配置文件异常:{error}",
                Data = false
            };
        }

        public Result<bool> UnZipDeviceDll()
        {
            if (Config.Device == null || Config.Device.Devices == null)
            {
                return new Result<bool>()
                {
                    Code = 1,
                    Message = "UnZipDeviceDll: 客户端配置信息为空"
                };
            }

            var list = new List<string>(){ "UnZipDeviceDll: " };
            var isErr = false;
            var dir = AppDomain.CurrentDomain.BaseDirectory;
            try
            {
                foreach (var device in Config.Device.Devices)
                {
                    if (device.DllZip != null && device.DllZipId != null && device.DllZipId != Guid.Empty)
                    {
                        var path = $"{dir}{device.DllZip.FileName}";
                        //判断DLL文件是否更新
                        if (File.Exists(path))
                        {
                            var bytes = File.ReadAllBytes(path);
                            if (device.DllHash == Md5Hash(new MemoryStream(bytes))) continue;
                        }
                        var httpItem = new HttpItem();
                        httpItem.URL = $"{Config.Local.Server}/api/_file/GetFile/{device.DllZipId}";
                        httpItem.ResultType = ResultType.Byte;
                        var httpResult = new HttpHelper().GetHtml(httpItem);
                        if (httpResult.StatusCode == HttpStatusCode.OK)
                        {
                            try
                            {
                                File.WriteAllBytes(path, httpResult.ResultByte);
                                UnzipFromStream(new MemoryStream(httpResult.ResultByte),
                                    AppDomain.CurrentDomain.BaseDirectory);
                                list.Add($"{device.Name}DLL文件更新完成");
                            }
                            catch (Exception e)
                            {
                                isErr = true;
                                list.Add($"{device.Name}保存和解压缩文件异常:{JsonConvert.SerializeObject(e)}");
                            }
                        }
                        else
                        {
                            isErr = true;
                            list.Add($"{device.Name}DLL下载失败");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                list.Add($"未知错误:{JsonConvert.SerializeObject(ex)}");
            }
            return new Result<bool>()
            {
                Code = isErr ? 1 : 200,
                Message = string.Join(" | ", list)
            };
        }

        private string Md5Hash(Stream stream)
        {
            byte[] hash = new MD5CryptoServiceProvider().ComputeHash(stream);
            StringBuilder stringBuilder = new StringBuilder();
            foreach (byte num in hash)
                stringBuilder.Append(num.ToString("x2"));
            return stringBuilder.ToString();
        }

        private void UnzipFromStream(Stream zipStream, string outFolder)
        {
            using (var zipInputStream = new ZipInputStream(zipStream))
            {
                while (zipInputStream.GetNextEntry() is ZipEntry zipEntry)
                {
                    var entryFileName = zipEntry.Name;
                    var buffer = new byte[4096];

                    var fullZipToPath = Path.Combine(outFolder, entryFileName);
                    var directoryName = Path.GetDirectoryName(fullZipToPath);
                    if (!string.IsNullOrEmpty(directoryName)) Directory.CreateDirectory(directoryName);

                    if (Path.GetFileName(fullZipToPath).Length == 0)
                    {
                        continue;
                    }

                    using (FileStream streamWriter = File.Create(fullZipToPath))
                    {
                        StreamUtils.Copy(zipInputStream, streamWriter, buffer);
                    }
                }
            }
        }
    }
}
